#include "bsp_qspi.h"


/* BSP-QSPI */

/**
 * QSPI使用BK2
 * 
 * QSPI_BK2_NCS : PC11
 * QSPI_CLK     : PB2
 * QSPI_BK2_IO0 : PE7
 * QSPI_BK2_IO1 : PE8
 * QSPI_BK2_IO2 : PE9
 * QSPI_BK2_IO3 : PE10
 * 
 */

/* static var */

static QSPI_HandleTypeDef qspi_handle;

/* export func */

/**
 * @brief 初始化QSPI
 * 
 * @param flash_size 目标flash大小
 */
void bsp_qspi_init(const uint32_t flash_size)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    __HAL_RCC_QSPI_CLK_ENABLE();    //QSPI时钟源见bsp_clock配置
    __HAL_RCC_QSPI_FORCE_RESET();
    __HAL_RCC_QSPI_RELEASE_RESET();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();

    /* QSPI_BK2_NCS: PC11 - AF9*/
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* QSPI_CLK: PB2 - AF9*/
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* QSPI_BK2_IO0-QSPI_BK2_IO3: PE7-PE10 - AF10*/
    GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* QSPI初始化 */
    memset(&qspi_handle, 0x00, sizeof(QSPI_HandleTypeDef));
    qspi_handle.Instance = QUADSPI;
    // if (HAL_QSPI_DeInit(&qspi_handle) != HAL_OK)
    {
        // Error_Handler(__FILE__, __LINE__);
    }

    qspi_handle.Instance = QUADSPI;
    qspi_handle.Init.ClockPrescaler = 1;     //时钟速度: QSPI clock = 240MHz / (ClockPrescaler+1) = 120MHz
    qspi_handle.Init.FifoThreshold = 4;      //FIFO阈值: 1-32
    qspi_handle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;    //采样移位半个周期
    qspi_handle.Init.FlashSize = POSITION_VAL(flash_size) - 1;//W25Q128大小为32M字节,2^25，所以取权值25-1=24，以此类推
    qspi_handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE;     //CS片选高电平保持时钟周期
    qspi_handle.Init.ClockMode = QSPI_CLOCK_MODE_0;  //MODE0,空闲时CLK时钟低电平; MODE3,空闲时CLK时钟高电平
    qspi_handle.Init.FlashID = QSPI_FLASH_ID_2;      //BK2
    qspi_handle.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
    if (HAL_QSPI_Init(&qspi_handle) != HAL_OK)
    {
        // Error_Handler(__FILE__, __LINE__);
    }
}

QSPI_HandleTypeDef *bsp_qspi_get_handle(void)
{
    return &qspi_handle;
}

void bsp_qspi_deinit(void)
{
    /* 复位GPIO */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_11);
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_2);
    HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10);

    /* 复位QSPI */
    __HAL_RCC_QSPI_FORCE_RESET();
    __HAL_RCC_QSPI_RELEASE_RESET();

    /* 关闭QSPI时钟 */
    __HAL_RCC_QSPI_CLK_DISABLE();

    if (HAL_QSPI_DeInit(&qspi_handle) != HAL_OK)
	{
		// Error_Handler(__FILE__, __LINE__);
	}
}
